package com.sk.sk_frame_cloud.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sk.sk_frame_cloud.config.DynamicDataSourceHolder;
import com.sk.sk_frame_cloud.constants.DynamicSourceConstant;
import com.sk.sk_frame_cloud.constants.ProManageStatus;
import com.sk.sk_frame_cloud.entity.ApplicationEntity;
import com.sk.sk_frame_cloud.entity.DataSourceInfo;
import com.sk.sk_frame_cloud.entity.SysProInfo;
import com.sk.sk_frame_cloud.entity.SysProManage;
import com.sk.sk_frame_cloud.mapper.SysProInfoMapper;
import com.sk.sk_frame_cloud.param.ProInfoParam;
import com.sk.sk_frame_cloud.res.CommonResponse;
import com.sk.sk_frame_cloud.service.IPropertiesServer;
import com.sk.sk_frame_cloud.service.ISysProInfoService;
import com.sk.sk_frame_cloud.service.ISysProManageService;
import com.sk.sk_frame_cloud.util.DataSourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jiaok
 * @since 2023-12-15
 */
@Service
@Slf4j
public class SysProInfoServiceImpl extends ServiceImpl<SysProInfoMapper, SysProInfo> implements ISysProInfoService {


    @Resource
    private ISysProManageService iSysProManageService;

    @Resource
    private IPropertiesServer iPropertiesServer;


    @Resource
    private DataSourceUtil dataSourceUtil;

    @Override
    public CommonResponse createProInfo(ProInfoParam proInfoParam) {
        log.info("===========================  SysProInfoServiceImpl.createProInfo ===========================");
        //获取当前项目的path
        SysProManage sysProManage = iSysProManageService.getById(proInfoParam.getProManageSid());
        String proCode = sysProManage.getProCode();
        ApplicationEntity applicationEntity = new ApplicationEntity();
        BeanUtils.copyProperties(proInfoParam,applicationEntity);
        applicationEntity.setDatabaseName(sysProManage.getProCode());
        applicationEntity.setPath(sysProManage.getProCode());
        applicationEntity.setProPort(proInfoParam.getProPort());
        // TODO: 2023-12-15 如果初始化失败了，应该怎么做回退操作
        //进行项目初始化操作
        iPropertiesServer.initializePro(applicationEntity);


        // TODO: 2023-12-15 如果数据库初始化失败了，应该怎么回退
        //开始创建数据库
        DataSourceInfo dataSourceInfo = extractedDataSourceInfo(applicationEntity);
        try {
            dataSourceUtil.initDatabase(proCode,dataSourceInfo);
        } catch (SQLException | IOException e) {
            log.error("===========================  初始化{}失败  ===========================",proCode);
            log.error(e.getMessage(),e);
        }


        SysProInfo sysProInfo = new SysProInfo();
        BeanUtils.copyProperties(proInfoParam,sysProInfo);
        sysProInfo.setSid(IdUtil.getSnowflakeNextIdStr());
        sysProInfo.setCreateTime(LocalDateTime.now());
        sysProInfo.setUpdateTime(LocalDateTime.now());

        //切换至项目管理数据源
        DynamicDataSourceHolder.setDynamicDataSourceKey(DynamicSourceConstant.BASEDB);
        this.save(sysProInfo);
        iSysProManageService.updateProStatus(ProManageStatus.GENERATED.getValue(),proInfoParam.getProManageSid());

        return CommonResponse.ok();
    }



    /**
     * 获取数据库连接的相关信息
     * @param applicationEntity
     */
    private static DataSourceInfo extractedDataSourceInfo(ApplicationEntity applicationEntity) {
        DataSourceInfo dataSourceInfo = new DataSourceInfo();
        String databaseUrl="jdbc:mysql://"+ applicationEntity.getDatabaseIp()+":"+ applicationEntity.getDatabasePort()+"/"+ applicationEntity.getDatabaseName()
                +"?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
        dataSourceInfo.setUrl(databaseUrl);
        dataSourceInfo.setUserName(applicationEntity.getDatabaseUsername());
        dataSourceInfo.setPassword(applicationEntity.getDatabasePassword());
        return dataSourceInfo;
    }
}
